\chapter{USER ACTIONS用户操作行为}
\thispagestyle{empty}  
\section{User Actions(用户操作)}
GEANT4有两个用户初始化类和一个用户操作类，为了实现仿真，用户必须重载这些类的方法。它们需要用户定义探测器，指定使用的物理过程并且定义初始粒子如何产生。这些类在强制用户操作和初始化中有描述。

除此之外，用户还可以定义一些可选择的用户操作，在从steps中产生的event,tracks或者整个events过程中收集数据，或者在runs中进行数据累计，或者修改新的tracks的状态就像它们被创造。这些用户操作在可选择用户操作.中有相关的描述。

为了支持在上面提到的操作中数据的累积，在event产生和tracking过程中，用户可以定义容器对象的一些子类。这些在用户信息类中有描述。

\section{Mandatory User Actions and Initializations（强制用户操作和初始化）}三个用户初始化类对象在用户main()函数的run manager中注册，获取所有权。用户一定不能直接清除这些对象，而且它们的创建必须通过‘new’。在G4UserActionInitialization 类（用户操作初始化）中，用户必须举例并注册一个具体的G4VuserPrimaryGeneratorAction 子类，这个子类在每个event中产生初级粒子。
\subsection{G4VUserDetectorConstruction}
\begin{lstlisting}[caption={G4VUserDetectorConstruction}]
class G4VUserDetectorConstruction
{ public:
G4VUserDetectorConstruction(); virtual ~G4VUserDetectorConstruction();
public:
virtual G4VPhysicalVolume* Construct() = 0; virtual void ConstructSDandField() = 0;
};
\end{lstlisting}
在Construct()中，材料和几何体已经被描述了。材料和几何体在如何在探测器中指定材料和如何定义探测器几何这两个小节中进行了详细的讨论。灵敏探测器和电磁场应该在ConstructSDandField()中定义，如果它们在多线程模型中使用，那么这个方法定义的对象是局部线程变量。灵敏探测器和电磁场在击中和电磁场小节中进行了详细的讨论。
\subsection{Physics Lists（物理列表）}
物理列表的概念是由于GEANT4无法为所有已知的过程和粒子提供单一的算法模型去覆盖整个从0到TeV的能量区间。取而代之的是结合不同的想法和方法去进行一次模拟任务。

GEANT4A模型粒子过程的简称可以通过如下表述：

•	物理模型 =最终状态产生器

•	物理过程 = 反应截面+模型

•	物理列表 =每个粒子的过程列表

拼凑的概念在GEANT4强子物理领域尤为正确：模型只在有限的能量范围内是有效的，在相同的区间内两种模型可能相互矛盾，也可能对于一个特定的粒子组一种模型工作效果比另一个好，与此同时它的竞争者可能更适合另一种类型的粒子。由于此种原因模型必须要相互结合来覆盖大的能量范围，每两个临近的模型之间在它们的有效区间内可能会有重复。

\subsubsection{G4VUserPhysicsList}
这是一个创建粒子和过程的抽象类。对GEANT4物理列表和GEANT4物理过程内容的介绍在如何指定物理过程和之后的物理过程都有所涉及。

虽然一个物理列表的制作原则上是用户的选择，但是为了方便许多用户的应用，工具箱被分配了很多预制物理列表。这些物理列表由GEANT4开发团队支持并且被推荐到指定的物理任务。然而基于兴趣和特定项目需要，用户可能想要实现他或她自己的自定义物理列表。

下面部分提供了几个例子展示怎样从GEANT4标准集合中实例化或选择一个或另一个预制物理列表，以及指导从预制成分甚至是完全从头开始的组成一个常规的物理列表。

为了看到一个物理列表的内容，下面是两个非常有用的方法：DumpList() and DumpCutValueTable(G4int flag)
\subsubsection{Reference Physics Lists（参考物理过程）}
大量准备好的物理列表在GEANT4内核中是可用的。下面给出FTFP\_BERT物理列表类实例化的例子。参考物理列表的完整集合在GEANT4网页中。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
G4int verbose = 1; FTFP_BERT* physlist = new FTFP_BERT(verbose);
 runManager->SetUserInitialization(physlist);
\end{lstlisting}
\subsubsection{Building Physics List Using Factory（利用Factory创建物理列表）}
GEANT4提供了一个叫做G4PhysListFactory的类允许用户通过它的名字去定义物理列表。名称中的最后一个字符定义了一个电磁（EM）物理选项。默认情况下，使用标准电磁物理，‘\_EMV’对应标准选项1，‘\_EMX’对应标准选项2，‘\_LIV’对应电磁Livermore物理，‘\_PEN’对应电磁Penelope物理
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.3:通过名字创建物理列表
G4int verbose = 1;
G4PhysListFactory factory; G4VModularPhysicsList* physlist = factory.GetReferencePhysList("FTFP_BERT_EMV"); physlist.SetVerboseLevel(verbose); runManager->SetUserInitialization(physlist);
\end{lstlisting}
G4PhysListFactory类也提供了另一个窗口，允许通过环境变量PHYSLIST定义物理列表
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.4:通过名字创建物理列表
G4int verbose = 1;
G4PhysListFactory factory; G4VModularPhysicsList* physlist = factory.ReferencePhysList(); physlist.SetVerboseLevel(verbose); runManager->SetUserInitialization(physlist);
\end{lstlisting}
\subsubsection{Building Physics List from Physics Builders（从物理建造者中建立物理列表）}

从技术上来讲，我们可以以“平出”的方式实现物理列表，即在一段代码中指定所有必要的粒子和相关过程，如本文档后面所示。然而，为了实际目的，将某些类别分组并使实现更模块化通常更为方便。

一个非常有用的概念是模块化的物理列表，G4VmodularPhysicsList，这是G4VuserPhysicsLists的子类，允许用户将物理过程组织成‘积木’或者’模块’中，然后将这样的模块组成一个物理列表。这个概念允许讲一些期望的选定的粒子和相应过程在一个相对高水平组织到一起。这种方法的一个优点是允许将GEANT4内核和用户应用集中提供的预制的物理模块结合到一起。

G4ModularPhysicsList具有G4VuserPhysicsList类的所有功能，加上一些额外的功能。其中一个重要的方法是RegisterPhysics(G4VPhysicsConstructor* )用来注册上面提到的预制物理模块。还有一些方法是移除或替代物理模块。

下面的例子展示了是怎么使用G4VmodularPhysList的
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.5:通过名字创造物理列表
MyPhysicsList::MyPhysicsList():G4VModularPhysicsList()
{
G4DataQuestionaire it(photon, neutron, no, no, no, neutronxs);
G4cout << "<<< Geant4 Physics List: MyPhysicsList " <<G4endl; G4cout <<G4endl; defaultCutValue = 0.7*mm; G4int ver = 1;
SetVerboseLevel(ver);
// EM Physics
RegisterPhysics( new G4EmStandardPhysics(ver) );
// Synchroton Radiation & GN Physics
RegisterPhysics( new G4EmExtraPhysics(ver) );
// Decays
RegisterPhysics( new G4DecayPhysics(ver) );
// Hadron physics
RegisterPhysics( new G4HadronElasticPhysicsXS(ver) );
RegisterPhysics( new G4QStoppingPhysics(ver) );
RegisterPhysics( new G4IonBinaryCascadePhysics(ver) );

RegisterPhysics( new G4HadronInelasticQBBC(ver));
// Neutron tracking cut
RegisterPhysics( new G4NeutronTrackingCut(ver) );
}
\end{lstlisting}
请注意，每个被注册到模块化物理列表中的模块都是一个G4VphysicsConstructor（或者一个派生对象），即保存粒子群或者伴随物理过程的子列表。用户可以在GEANT4核心源代码source/physics\_lists/list区域的找到这些或者其它相似的模块，并如果需要可以将选定的模块与典型模块相结合。

为了组成一个常见的物理模块，必须实现两个强制的G4VphysicsConstructor的方法：ConstructParticle() and ConstructProcess()；除此之外可以根据开发者的喜好构造实现。

在模块方法中另一个有用的概念是所谓的生成器概念。这个概念允许将某些实现细节封装到一个更小规模的软件组件中，并提供在不同模块中重新使用这些组件的灵活性。一般来说这个方案是这样的：

	粒子（强子）被创建，被用来模拟适用的过程的物理模型被指定，常常是在某个特定的有效范围内。

	在生成器中每个粒子类型的物理过程被创建，而且按照指定的每个过程配备一个或多个强子物理模型。

	如果必要，增加给定粒子类型的截面数据集

这个概念被广泛应用于GEANT4的强子领域，但是这个思想同样适用于电磁场区域。

所有的生成器可以在source/physics\_lists/builders目录中找到。基本有两种类型的建造者：

	粒子生成器

	粒子-模型 生成器

一个粒子生成器在这里有些优越性，因为它指定一个粒子或者粒子群，指定哪些过程范畴是适用的，如何用指定的模型去装配过程以及如何用G4ProcessManager注册物理过程。粒子模型生成器对给定模型进行实例化并实现关联细节。它具有适用于给定粒子类型的一个或多个过程。一些模型不能通过一个单独的接口类来实例化，但是反过来它们需要由几个组件组成（例子是QGS和FTF）

有用的例子生成器作为灵感检验和参考如下所示：

	G4PiKBuilder (.hh 和 .cc) –群π介子和k中介子以及相关强子过程的列表。

	G4BertiniPiKBuilder (.hh和 .cc)-实例化的Beltll级联模型并实现用这个模型如何配置π介子和k中介子物理过程。它还为模型设置了默认有效范围。

	G4FTFPPiKBuilder (.hh和.cc)-构成一个高能的基于FTF的模型并实现如何用这个模型为π介子和k中介子配置强子过程。这个例子说明一个强子模型并不总是有一个单独的接口类，但是它需要从几个组件中创建。尤其是在这个生成器中一个‘高能产生器’的类（G4TheoFSGenerator）被创建并用G4FTFModel字符串模型配置（它也给出了这个生成器的名字），这也是字符串分割算法和核内传输模型。请注意，准弹性散射的设置和FTF模型不同，它有自己的设置机制。π介子的截面数据库是指定的。还指定了默认有效范围。

需要记住的一个细节就是，原则上可以为每个粒子类型单独的建立一个给定模型的有效范围。但是在这些引用的应用中，对于一组粒子，有效范围要设置为相同（对于一些对应的非弹性强子过程）。一旦实例化生成器，用户就可以重载默认的有效范围（通过SetMinEnergy 或SetMaxEnergy方法），但是新值将再次给出一组粒子/过程。还要注意，只有在调用生成器的Build()方法，有效范围才能被重载。同样，该方法只是具体实现的一个细节。很明显，如果针对一个特定的粒子/模型/过程选择有效范围，一个必须补充另一个模型或另几个模型以覆盖整个范围。

一个更有用的类是‘‘ G4PhysicsListHelper‘‘，它是围绕在GEANT4中注册的物理过程的技术性的服务类，并且允许和用户方便的将一个过程和粒子相关联，并不需要知道各种类型的过程（离散、连续等）以及G4ProcessManager中它们的内部排序。好奇的用户可能最终想深入了解G4ProcessManager类，尤其是它的AddProcess(...)方法。因为它是实现G4PhysicsListHelper的基础。但是出于实用目的，在大多数情况下使用G4PhysicsListHelper已经足够了。

其它的有用的细节，包括一些软件设计理念的元素和类图将在How to Specify Physics Processes中提到。
用户必须从G4VuserPhysicsList中派生出一个具体类，并且实现三种虚方法：

	ConstructParticle() 用于实例化每个被请求的粒子类型;

	ConstructPhysics() 用于实例化期望的物理过程并注册每个过程

	SetCuts(G4double aValue) 为粒子表中的所有粒子设置一个射程截断值，它将引起物理表的重建

在GEANT4初始化早期阶段，调用G4VuserPhysicsList中ConstructParticle()的方法。为了保证粒子的输运，ConstructProcess()方法必须始终调用AddTransportation()。AddTransportation()绝对不能被重载。如果G4VuserPhysicsList继承了G4VmodularPhysicsList，那么这个将自动完成。建议用户将这个作为物理列表中最强壮的接口。GEANT4例子说明如何用不同方法创建用户物理列表。

\subsection{User Action Initialization（用户操作初始化）}
所有用户操作类必须通过受保护的SetUserAction()方法定义。Build()方法应该为工作线程和顺序模式操作定义用户操作类。BuildForMaster()仅仅用于定义UserRunAction的主线程。BuildForMaster()不能再顺序模式中调用，在用户使用他或她自己的SteppingVerbose类时，必须在InitializeSteppingVerbose()方法中实例化并返回。

\subsubsection{G4VUserActionInitialization}
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.6: G4VUserActionInitialization
class G4VUserActionInitialization
{ public:
G4VUserActionInitialization(); virtual ~G4VUserActionInitialization();
public:
virtual void Build() const = 0; virtual void BuildForMaster() const; virtual G4VSteppingVerbose* InitializeSteppingVerbose() const;
protected:
void SetUserAction(G4VUserPrimaryGeneratorAction*) const; void SetUserAction(G4UserRunAction*) const; void SetUserAction(G4UserEventAction*) const; void SetUserAction(G4UserStackingAction*) const; void SetUserAction(G4UserTrackingAction*) const;
void SetUserAction(G4UserSteppingAction*) const;
};
\end{lstlisting}
\subsubsection{G4VUserPrimaryGeneratorAction}
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.7: G4VUserPrimaryGeneratorAction
class G4VUserPrimaryGeneratorAction
{ public:
G4VUserPrimaryGeneratorAction(); virtual ~G4VUserPrimaryGeneratorAction();
public:
virtual void GeneratePrimaries(G4Event* anEvent) = 0; };
\end{lstlisting}
\section{Optional User Actions（可选的用户操作）}
有5个虚类，用于增强在不同阶段对模拟的控制，用户必须重载这些类的方法。每个操作类的方法都有一个空的缺省实现，允许用户继承并实现期望的类和方法。

用户操作类的对象必须向G4RunManager(管理运行过程)注册，这些进程拥有它们的所有权。用户不能直接删除这些对象，并且必须用‘new’创建它们
\subsection{Usage of User Actions}
\subsubsection{G4UserRunAction}
这个类有三个虚方法，它们由G4RunManager为每个run调用：

	GenerateRun() 这个方法在BeamOn开始时被调用。因为用户可以继承类G4Run并建立他/她自己的具体类，用于存储和run相关的一些信息，这个GenerateRun()方法就是实例化这个具体类的地方。这个方法也是为一个特殊的run 设置那些影响物理表（比如产生阈值）的变量的地方，因为GenerateRun()在物理表计算之前调用。

	BeginOfRunAction() 这个方法在进入event循环之前被调用。这个方法的典型使用是为了一个特殊的run初始化和/或预定histograms。这个方法在物理表之后被 调用。

	EndOfRunAction() 这个方法在run处理的结尾被调用。它一般用于对运行完成的run进行一些简单分析。

\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.8: G4UserRunAction
class G4UserRunAction
{ public:
G4UserRunAction(); virtual ~G4UserRunAction();
public:
virtual G4Run* GenerateRun(); virtual void BeginOfRunAction(const G4Run*);
virtual void EndOfRunAction(const G4Run*);
};
\end{lstlisting}
\subsubsection{G4UserEventAction}
这个类有两个虚方法，G4EventManager为每个event调用它们：

	beginOfEventAction() 这种方法在将初级粒子转换为G4Track对象之前被调用。这个方法的典型使用是为了一个特殊的事件初始化和/或预定histograms 。

	endOfEventAction() 这个方法在event处理的结尾被调用。它一般用于对处理完的event进行简单的分析。如果用户希望保持当前处理事件直到当前运行的结果，用户可以调用fpEventManager->KeepTheCurrentEvent()；以至于可以保存在G4Run的对象中。如果你模拟很多event并且在长时间的执行之后只想可视化最感兴趣的那部分，这种方法应该非常有用。考虑到event的内存大小而且它的内容可能很大，用户没必要保持不需要的events。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.9: G4UserEventAction
class G4UserEventAction
{ public:
G4UserEventAction() {;} virtual ~G4UserEventAction() {;} virtual void BeginOfEventAction(const G4Event*); virtual void EndOfEventAction(const G4Event*);
protected:
G4EventManager* fpEventManager;
};
\end{lstlisting}
\subsubsection{G4UserStackingAction}
这个类有三个虚方法，ClassifyNewTrack, NewStage和 PrepareNewEvent，为了控制各种track的栈机制，用户可以对它们进行重载。ExampleN04可能是一个理解怎么使用这个类的很好的例子。

无论什么时候，只要一个新的G4Track对象被G4EventManager 压入堆栈中，ClassifyNewTrack()就会通过G4StackManager调用。ClassifyNewTrack()返回一个枚举对象G4ClassificationOfNewTrack，它的值表明track将被发送到哪个栈。这个值应该由用户确定。G4ClassificationOfNewTrack有四个可能值：

	fUrgent - track 被放在 urgent 栈中

	fWaiting - track 被放在waiting栈中, 并且直到urgent栈为空的时候才会被模拟

	fPostpone – track被推迟到下一个 event中

	fKill – track被立即删除，并为保存到任何栈。

这些基于track起点生成的值。可以用下面方法获取：
\begin{lstlisting}
G4int parent_ID = aTrack->get_parentID();
\end{lstlisting}
这里

	parent\_ID = 0 表示初级粒子

	parent\_ID > 0 表示次级粒子

	parent\_ID < 0表示一个来自前个事件被推迟的粒子

当urgent栈为空且waiting栈包含至少一个对象的时候，将调用NewStage()。这里用户可以通过调用stackManager->ReClassify()方法，将在waiting栈中的所有tracks杀掉，或者重新分配到不同的栈，stackManager->ReClassify()将调用ClassifyNewTrack()方法。如果没有使用任何用户操作，waiting栈中所有的tracks将被转移到urgent栈中。尽管在waiting栈中可能存在一些tracks，用户也可以决定通过调用stackManager->clear()来中止当前事件。只有从G4UserStackingAction类中调用这些方法才是安全的。中止事件的全局方法是：
\begin{lstlisting}
G4UImanager * UImanager = G4UImanager::GetUIpointer();
UImanager->ApplyCommand("/event/abort");
\end{lstlisting}
PrepareNewEvent()在每个event开始的时候调用。在这个时刻没有初级粒子被转换成tracks，所以urgent和waiting栈是空的。然而可能在postponed-tonext-event栈中存在一些tracks；每次track将调用ClassifyNewTrack()方法，这个track将被分配到合适的栈中。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.10: G4UserStackingAction
#include "G4ClassificationOfNewTrack.hh"
class G4UserStackingAction
{ public:
G4UserStackingAction(); virtual ~G4UserStackingAction();
protected:
G4StackManager * stackManager;
public:
//---------------------------------------------------------------
// virtual methods to be implemented by user
//---------------------------------------------------------------
// virtual G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track*); virtual void NewStage(); virtual void PrepareNewEvent();
};
\end{lstlisting}
\subsubsection{G4UserTrackingAction}
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.11: G4UserTrackingAction
//---------------------------------------------------------------
// G4UserTrackingAction.hh
//
// Description:
// This class represents actions taken place by the user at // the start/end point of processing one track.
//---------------------------------------------------------------
class G4UserTrackingAction
{ public:
// Constructor & Destructor G4UserTrackingAction(){}; virtual ~G4UserTrackingAction(){}
// Member functions virtual void PreUserTrackingAction(const G4Track*){} virtual void PostUserTrackingAction(const G4Track*){}
protected:
G4TrackingManager* fpTrackingManager;
};
\end{lstlisting}
\subsubsection{G4UserSteppingAction}
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.12: G4UserSteppingAction
//---------------------------------------------------------------
// G4UserSteppingAction.hh
//
// Description:
//	This class represents actions taken place by the user at each //	end of stepping.
//---------------------------------------------------------------
class G4UserSteppingAction
{ public:
// Constructor and destructor G4UserSteppingAction(){} virtual ~G4UserSteppingAction(){}
// Member functions virtual void UserSteppingAction(const G4Step*){}
protected:
G4SteppingManager* fpSteppingManager;
};
\end{lstlisting}
\subsection{Killing Tracks in User Actions and Energy Conservation（在用户操作和能量转换中杀死tracks）}
在前一节中描述的用户操作类中，用户可以实现非自然/非物理操作。一个典型的粒子是在用户的stepping操作中杀死一个正在仿真的轨迹。在这种情况下，用户必须小心总能量守恒。用户的stepping操作本身并不关心能量或其它任何和杀死track有关的物理量。因此如果用户想要在这种情况下保持一个event的总能量，丢失的轨道能量需要由用户记录。

用户栈或者tracking操作也是如此。如果用户在这些操作中杀死一个tracking，那么与它相关联的所有物理信息都将丢失，比如总能量守恒将被破坏。
如果用户希望GEANT4内核在他/她人工杀死一个track时总能量守恒，那么用户必须使用杀手（killer）过程。比如，如果用户使用G4UserLimits 和 G4UserSpecialCuts过程，那么被杀死的track的能量会被添加到总能量沉积当中。

\section{User Information Classes（用户信息类）}
附加用户信息可以与各种GEATN4类相关联。基本上有两种方法让用户这样做：

从GEANT4的基类中派生出具体类。这些类是run, 击中, 数字化, 轨迹和轨迹点的类，在Optional User Actions中讨论，分别是G4Run, 击中用 G4VHit, 数字化用 G4VDigit, tracking用G4VTrajectory and G4VtrajectoryPoint
从提供的抽象基类创建具体类，并将它们与GEANT4中使用的类相关联。可以容纳用户信息类：G4Event, G4Track, G4PrimaryVertex, G4PrimaryParticle and G4Region。这里讨论这些类。

\subsection{G4VUserEventInformation}
G4VuserEventInformation是一个抽象类，用户可以从中派生出他/她自己的具体类，用于存储与G4Event类对象相关的用户信息。用户需要构造一个具体类对象并将指针甚至为一个合适的G4Event对象。

在G4UserEventAction的具体实现中，G4EventManager的SetUserEventInformation()方法可以用于将一个具体类对象的指针设置为G4Event，因为G4Event对象仅可用于“固定指针”。或者，用户可以修改他或她的RunManager 中GenerateEvent()的方法实例化G4VuserEventInformation信息对象并将其设置为G4Event。

当关联G4Event对象被清除的时候，具体类对象也被GEANT4内核清除。

\subsection{G4VUserTrackInformation}
这是一个抽象类，用户可以从中派生他/她自己的具体类，用于存储与G4Track类对象相关联的用户信息。用户需要构造一个具体类对象并将指针甚至为一个合适的G4Track对象。

在G4UserTrackAction的具体实现中，G4TrackManager的SetUserTrackInformation()方法可以用于将一个具体类对象的指针设置为G4Track，因为G4Track对象仅可用于“固定指针”。

从一个母track复制一个 G4VuserTrackInformation对象到它的子track的理想场所是G4UserTrackingAction::PostUserTrackingAction()。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
Listing 6.13: Copying G4VUserTrackInformation from mother to daughter tracks
void RE01TrackingAction::PostUserTrackingAction(const G4Track* aTrack) {
G4TrackVector* secondaries = fpTrackingManager->GimmeSecondaries(); if(secondaries) {
RE01TrackInformation* info = (RE01TrackInformation*)(aTrack->GetUserInformation()); size_t nSeco = secondaries->size(); if(nSeco>0) { for(size_t i=0; i < nSeco; i++)
{
RE01TrackInformation* infoNew = new RE01TrackInformation(info);
(*secondaries)[i]->SetUserInformation(infoNew);
}
}
}
}
\end{lstlisting}
当关联G4Track对象被清除的时候，具体类对象也被GEANT4内核清除。在这种情况下如果用户想保存信息，就应该复制和track相关的轨道。

\subsection{G4VUserPrimaryVertexInformation and G4VUserPrimaryTrackInformation}
这些抽象类允许用户附加关于生成初级顶点和初级粒子的信息。从这些类派生的具体类对象应该分别附着到G4PrimaryVertex和G4PrimaryParticle类对象。

当关联G4PrimaryVertex 或 G4PrimaryParticle对象被G4Event清除的时候，具体类对象也被GEANT4内核清除。

\subsection{G4VUserRegionInformation}
这个抽象基类允许用户附加与区域相关联的信息。比如，添加一些返回布尔标志来表明区域特征的方法（比如跟踪器和热量计等等）是非常有益的。通过这个例子，用户可以容易且快速地识别探测器组件。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例 6.14:区域信息类使用的例子
class RE01RegionInformation : public G4VUserRegionInformation
{ public:
RE01RegionInformation(); ~RE01RegionInformation(); void Print() const;
private:
G4bool isWorld;
G4bool isTracker;
G4bool isCalorimeter;
public:
inline void SetWorld(G4bool v=true) {isWorld = v;} inline void SetTracker(G4bool v=true) {isTracker = v;} inline void SetCalorimeter(G4bool v=true) {isCalorimeter = v;} inline G4bool IsWorld() const {return isWorld;} inline G4bool IsTracker() const {return isTracker;} inline G4bool IsCalorimeter() const {return isCalorimeter;} };
\end{lstlisting}
下面的代码是一个stepping操作的粒子。当它从“跟踪器区域（tracker region）”到达“热量计区域（calorimeter region）”时， track被暂停。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.15:区域信息类使用的例子
void RE01SteppingAction::UserSteppingAction(const G4Step * theStep) {
// Suspend a track if it is entering into the calorimeter
// check if it is alive
G4Track * theTrack = theStep->GetTrack(); if(theTrack->GetTrackStatus()!=fAlive) { return; }
// get region information
G4StepPoint * thePrePoint = theStep->GetPreStepPoint();
G4LogicalVolume * thePreLV = thePrePoint->GetPhysicalVolume()->GetLogicalVolume();
RE01RegionInformation* thePreRInfo
= (RE01RegionInformation*)(thePreLV->GetRegion()->GetUserInformation()); G4StepPoint * thePostPoint = theStep->GetPostStepPoint();
G4LogicalVolume * thePostLV = thePostPoint->GetPhysicalVolume()->GetLogicalVolume();
RE01RegionInformation* thePostRInfo
= (RE01RegionInformation*)(thePostLV->GetRegion()->GetUserInformation());
// check if it is entering to the calorimeter volume if(!(thePreRInfo->IsCalorimeter()) && (thePostRInfo->IsCalorimeter())) { theTrack->SetTrackStatus(fSuspend); }
}
\end{lstlisting}
\section{Multiple User Actions（多个用户操作类）}
从GEANT4.10.3开始可以将同一类型的用户操作的多个实例附加到单个运行管理器。这是通过使用附加多个子用户操作的特殊代理类来实现的。这允许运行run-, event-, tracking- 和stepping- 用户操作（G4UserRunAction, G4UserEventAction,G4UserTrackingAction,G4UserSteppingAction）。
内核仍然可以看到每种类型的单用户操作，代理将从内核调用所有连接到子用户的操作。
\begin{lstlisting}[caption={创建FTFP\_BERT物理列表}]
举例6.16:用户使用多个用户操作的例子
#include "G4MultiRunAction.hh"
#include "G4MultiEventAction.hh"
#include "G4MultiTrackingAction.hh"
#include "G4MultiSteppingAction.hh" //... void MyUserActionInitialization::Build()
{ //...
// Example with multiple-event action, similarly
// for the other cases
// multi- user actions extend std::vector auto multiAction = new G4MultiEventAction { new MyEventAction1, new MyEventAction2 } ; //... multiAction->push_back( new MyEventAction3 );
SetUserAction( multiAction ); //...
}
\end{lstlisting}
\subsection{Exceptions（例外情况）}
对于栈用户操作和初始操作，没有实现此功能。没有多个G4UserStackingAction等效，因为这需要在出现冲突类是对其中的情况进行复杂的处理。对于G4VuserPrimaryGeneratorAction的情况，多用户操作的实例已经通过类本身的设计来解决。用户可以在操作中实现一个或多个生成器。
对于G4MultiRunAction的情况，只有一个子用户操作可以实现G4UserRunAction::GenerateRun()方法，返回非空的、用户派生的G4Run对象，否则会出现异常。
